package com.jintian.smart.kernel.flowable.flowable.cmd;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.jintian.smart.kernel.core.dto.OrgUnit;
import com.jintian.smart.kernel.core.flow.ProcessControl;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.el.ExpressionManager;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.ProcessEngines;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.delegate.ActivityBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.impl.util.TaskHelper;
import org.flowable.task.api.DelegationState;
import org.flowable.task.service.TaskService;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.util.Assert;

/**
 * 跳转
 */
public class TransformTaskCmd implements Command<List<TaskEntity>> {
    public static final String FLAG_TRANSFORM = "transform.backToOwner";
    private String taskId;
    private ProcessControl processControl;

    public TransformTaskCmd(String taskId, ProcessControl processControl) {
        this.taskId = taskId;
        this.processControl = processControl;
    }

    @Override
    public List<TaskEntity> execute(CommandContext commandContext) {
        List<TaskEntity> ret = new ArrayList<>();
        TaskService taskService = CommandContextUtil.getTaskService(commandContext);
        ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
        TaskEntity currentTask = taskService.getTask(taskId);
        ProcessControl.ProcessControlItem item = processControl.getFlowTos().get(0);
        List<OrgUnit> executors = item.getExecutors();
        Assert.isTrue(executors.size() > 0, "未指定执行者");
        ExecutionEntity currentExecutionEntity = executionEntityManager.findById(currentTask.getExecutionId());
        UserTask transformUserTask = TransformTaskCmd.createTransformUserTask(
                currentExecutionEntity.getProcessDefinitionId(), currentExecutionEntity.getProcessDefinitionKey(),
                currentTask.getTaskDefinitionKey());
        ExecutionEntity transfromParallelExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
                .createChildExecution(currentExecutionEntity);
        transfromParallelExecution.setCurrentFlowElement(transformUserTask);
        transfromParallelExecution.setMultiInstanceRoot(true);
        transfromParallelExecution.setActive(false);
        transfromParallelExecution.setVariableLocal("transformList",
                executors.stream().map(o -> o.getId()).collect(Collectors.toList()));
        ((ActivityBehavior) transformUserTask.getBehavior()).execute(transfromParallelExecution);

        // 设置为等待中
        currentTask.setDelegationState(DelegationState.PENDING);
        if (currentTask.getOwner() == null) {
            currentTask.setOwner(currentTask.getAssignee());
        }
        TaskHelper.changeTaskAssignee(currentTask, null);
        currentTask.setVariableLocal(TransformTaskCmd.FLAG_TRANSFORM, item.getVariables().get(TransformTaskCmd.FLAG_TRANSFORM));
        return ret;
    }

    public static UserTask createTransformUserTask(String processDefinitionId, String processDefinitionKey, String taskDefinitionKey) {
        BpmnModel model = ProcessDefinitionUtil.getBpmnModel(processDefinitionId);
        org.flowable.bpmn.model.Process process = model.getProcessById(processDefinitionKey);
        UserTask orgi = (UserTask) process.getFlowElement(taskDefinitionKey);
        UserTask activity = (UserTask) orgi.clone();
        activity.setIncomingFlows(orgi.getIncomingFlows());
        activity.setOutgoingFlows(orgi.getOutgoingFlows());
        MultiInstanceLoopCharacteristics loop = new MultiInstanceLoopCharacteristics();
        loop.setSequential(false);
        // 配置转发集合变量名称.
        loop.setInputDataItem("${transformList}");
        // 配置转发集合遍历名称.
        loop.setElementVariable("transform");
        activity.setAssignee("${transform}");
        activity.setLoopCharacteristics(loop);

        // 获取流程引擎配置实现类.
        ProcessEngineConfigurationImpl processEngineConfiguration = (ProcessEngineConfigurationImpl) ProcessEngines
                .getDefaultProcessEngine().getProcessEngineConfiguration();
        // 创建新的任务实例.
        UserTaskActivityBehavior userTaskActivityBehavior = processEngineConfiguration.getActivityBehaviorFactory()
                .createUserTaskActivityBehavior(activity);
        // 创建BPMN 2.0规范中描述的多实例功能.
        ParallelMultiInstanceBehavior behavior = new ParallelMultiInstanceBehavior(activity, userTaskActivityBehavior);
        // 设置下一节点多实例行为.
        activity.setBehavior(behavior);
        // 设置多实例元素变量.
        behavior.setCollectionElementVariable("transform");
        ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();
        // 设置多实例集合表达式.
        behavior.setCollectionExpression(expressionManager.createExpression("${transformList}"));
        return activity;
    }

}